
import { _decorator, Component, instantiate, Node, Prefab, random, Vec2, Vec3 } from 'cc';
import { Block } from './Block';
import { JoyStickManager } from '../utils/JoyStickManager';
import { CamreaCtrl } from '../game/CamreraCtrl';
import { Config } from '../utils/Config';
import { Tools } from '../utils/Tools';
const { ccclass, property } = _decorator;

/**
 * Predefined variables
 * Name = MapCtrl
 * DateTime = Sat Feb 24 2024 15:44:55 GMT+0800 (中国标准时间)
 * Author = heyongtao
 * FileBasename = MapCtrl.ts
 * FileBasenameNoExtension = MapCtrl
 * URL = db://assets/scripts/map/MapCtrl.ts
 * ManualUrl = https://docs.cocos.com/creator/3.4/manual/zh/
 *
 */
 
@ccclass('MapCtrl')
export class MapCtrl extends Component {
    // [1]
    // dummy = '';
    // map info
    public mapBlock : Block[][];
    public blockFixSize : number = Config.GetInstance().MapBlockFixSize;
    public mapBlockX : number = Config.GetInstance().MapMaxXBlockCnt;
    public mapBlockY : number = Config.GetInstance().MapMaxYBlockCnt;
    public visI : number = Config.GetInstance().MapInitI;  //可见范围
    public visJ : number = Config.GetInstance().MapInitJ;
    public lastMoveI : number = 0;
    public lastMoveJ : number = 0;
    public curMoveX : number = 0;
    public curMoveY : number = 0;
    // @property
    // serializableDummy = 0;
    @property(Prefab)
    blockPfb :  Prefab;
    @property(Prefab)
    block1Pfb : Prefab;

    protected onLoad(): void {
        this.mapBlock = new Array<Block[]>(this.mapBlockX).fill(null).map(() => new Array<Block>(this.mapBlockY).fill(null));
    }

    // getRandomInt(min : number, max) : number {  
    //     min = Math.ceil(min);  
    //     max = Math.floor(max);  
    //     return Math.floor(Math.random() * (max - min + 1)) + min;  
    // }  

    getRandPrefab()
    {
        return Tools.GetInstance().getRandomInt(0,1) == 0 ? this.blockPfb : this.block1Pfb;
    }

    start () {
        let initPos = new Vec2(0,0);
        let offsetX = 32;
        let offsetY = 32;
        // init map
        for(let i=0;i<this.visI;++i)
        {
            for(let j=0;j<this.visJ;++j)
            {
                this.mapBlock[i][j] = new Block();
                this.mapBlock[i][j].initBlock(this.node,this.getRandPrefab(),i,j,new Vec3(initPos.x+offsetX,initPos.y+offsetY,0))
                offsetY += 64;
            }
            offsetX += 64;
            offsetY = 32;
        }
    }
    updateBlockX(cx : number)
    {
        if(cx == 0) return ;
        this.curMoveX += cx;
        // 检查边界
        if(this.lastMoveI <= 0 && this.curMoveX <= -this.blockFixSize)
        {
            this.curMoveX -= cx;
        }
        if(this.lastMoveI >= this.mapBlockX && this.curMoveX >= this.blockFixSize )
        {
            this.curMoveX -= cx;
        }
        //if(!CamreaCtrl.GetInstance().checkPosXIsMovedOfPlayer()) 

        if(Math.abs(this.curMoveX) >= this.blockFixSize)
        {
            let dir = this.curMoveX > 0 ? 1 : 0;
            
            if(dir)
            {
                let cn = Math.floor(this.curMoveX / this.blockFixSize);
                for(let i=0;i<cn;++i)
                {
                    // 0 1 2 3 4 5 
                    // cn = 2
                    for(let j=0;j<this.visJ;++j)
                    {
                        let rmvI = this.lastMoveI + i;
                        let rmvJ = this.lastMoveJ + j;
                        let rmvBlock = this.mapBlock[rmvI][rmvJ];
                        //最后一个存在的block
                        let lastBlockI = rmvI+this.visI-1;
                        let lastBlock = this.mapBlock[lastBlockI][rmvJ];
                        if(!this.mapBlock[lastBlockI + 1][rmvJ])
                        {
                            this.mapBlock[lastBlockI + 1][rmvJ] = new Block();
                        }
                        this.mapBlock[lastBlockI + 1][rmvJ].resetBlock(lastBlock.pos.x+this.blockFixSize,rmvBlock.pos.y,lastBlockI + 1,rmvJ,rmvBlock);
                        this.mapBlock[rmvI][rmvJ] = null;
                    }               
                }
                this.lastMoveI += cn;
                this.curMoveX -= cn * this.blockFixSize;                
            }
            else
            {
                let cn = Math.floor(Math.abs(this.curMoveX) / this.blockFixSize);
                for(let i=0;i<cn;++i)
                {
                    // 0 1 2 3 4 5 
                    // cn = 2
                    for(let j=0;j<this.visJ;++j)
                    {
                        let rmvI = this.lastMoveI - i + this.visI-1;
                        let rmvJ = this.lastMoveJ + j;
                        let rmvBlock = this.mapBlock[rmvI][rmvJ];
                        //最后一个存在的block
                        let lastBlockI = this.lastMoveI-i;
                        let lastBlock = this.mapBlock[lastBlockI][rmvJ];
                        if(!this.mapBlock[lastBlockI - 1][rmvJ])
                        {
                            this.mapBlock[lastBlockI - 1][rmvJ] = new Block();
                        }
                        this.mapBlock[lastBlockI - 1][rmvJ].resetBlock(lastBlock.pos.x-this.blockFixSize,rmvBlock.pos.y,lastBlockI - 1,rmvJ,rmvBlock);
                        this.mapBlock[rmvI][rmvJ] = null;
                    }               
                }
                this.lastMoveI -= cn;
                this.curMoveX += cn * this.blockFixSize;  
            }
        }
    }

    updateBlockY(cy : number)
    {
        if(cy == 0) return;
        this.curMoveY += cy;
        //检查边界
        if(this.lastMoveJ <= 0 && this.curMoveY <= -this.blockFixSize)
        {
            this.curMoveY -= cy;
        }
        if(this.lastMoveJ >= this.mapBlockY && this.curMoveY >= this.blockFixSize)
        {
            this.curMoveY -= cy;
        }

        if(Math.abs(this.curMoveY) >= this.blockFixSize)
        {
            let dir = this.curMoveY > 0 ? 1 : 0;

            if(dir)
            {
                let cn = Math.floor(this.curMoveY / this.blockFixSize);
                for(let j=0;j<cn;++j)
                {
                    for(let i=0;i<this.visI;++i)
                    {
                        let rmvI = this.lastMoveI + i;
                        let rmvJ = this.lastMoveJ + j;
                        let rmvBlock = this.mapBlock[rmvI][rmvJ];

                        let lastBlockJ = rmvJ + this.visJ -1;
                        let lastBlock = this.mapBlock[rmvI][lastBlockJ];
                        if(!this.mapBlock[rmvI][lastBlockJ+1])
                        {
                            this.mapBlock[rmvI][lastBlockJ+1] = new Block();
                        }
                        this.mapBlock[rmvI][lastBlockJ+1].resetBlock(lastBlock.pos.x,lastBlock.pos.y+this.blockFixSize,rmvI,lastBlockJ+1,rmvBlock);
                        this.mapBlock[rmvI][rmvJ] = null;
                    }
                }
                this.lastMoveJ += cn;
                this.curMoveY -= cn * this.blockFixSize;
            }
            else
            {
                let cn = Math.floor(Math.abs(this.curMoveY) / this.blockFixSize);
                for(let j=0;j<cn;++j)
                {
                    for(let i=0;i<this.visI;++i)
                    {
                        let rmvI = this.lastMoveI + i;
                        let rmvJ = this.lastMoveJ - j + this.visJ - 1;
                        let rmvBlock = this.mapBlock[rmvI][rmvJ];

                        let lastBlockJ = this.lastMoveJ -j;
                        let lastBlock = this.mapBlock[rmvI][lastBlockJ];
                        if(!this.mapBlock[rmvI][lastBlockJ-1])
                        {
                            this.mapBlock[rmvI][lastBlockJ-1] = new Block();
                        }
                        this.mapBlock[rmvI][lastBlockJ-1].resetBlock(lastBlock.pos.x,lastBlock.pos.y-this.blockFixSize,rmvI,this.lastMoveI-1,rmvBlock);
                        this.mapBlock[rmvI][rmvJ] = null;
                    }
                }
                this.lastMoveJ -= cn;
                this.curMoveY += cn * this.blockFixSize;
            }
        }
    }

    // 根据摄像机的位置去更新Map
    updateMapBlock()
    {
        let cx = CamreaCtrl.GetInstance().getCX();
        let cy = CamreaCtrl.GetInstance().getCY();
        //console.log("cx:",cx,"  cy:",cy)
        if(cx != 0)
        {
            this.updateBlockX(cx);
        }
        if(cy != 0)
        {
            this.updateBlockY(cy);
        }
    }

    update (deltaTime: number) {
        if(JoyStickManager.GetInstance().joyStick.moving)
        {
            this.updateMapBlock();
        }
    }
}

/**
 * [1] Class member could be defined like this.
 * [2] Use `property` decorator if your want the member to be serializable.
 * [3] Your initialization goes here.
 * [4] Your update function goes here.
 *
 * Learn more about scripting: https://docs.cocos.com/creator/3.4/manual/zh/scripting/
 * Learn more about CCClass: https://docs.cocos.com/creator/3.4/manual/zh/scripting/decorator.html
 * Learn more about life-cycle callbacks: https://docs.cocos.com/creator/3.4/manual/zh/scripting/life-cycle-callbacks.html
 */
